package com.njegovanobradovic.icet.facade.impl;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.Session;

import com.njegovanobradovic.icet.facade.Controller;
import com.njegovanobradovic.icet.metamodel.Chat;
import com.njegovanobradovic.icet.metamodel.Message;
import com.njegovanobradovic.icet.metamodel.Room;
import com.njegovanobradovic.icet.metamodel.User;
import com.njegovanobradovic.icet.metamodel.beans.MessageBean;
import com.njegovanobradovic.icet.metamodel.beans.RoomBean;
import com.njegovanobradovic.icet.service.Add;
import com.njegovanobradovic.icet.service.Delete;
import com.njegovanobradovic.icet.service.Get;
import com.njegovanobradovic.icet.service.GetChatMessages;
import com.njegovanobradovic.icet.service.GetChatUsers;
import com.njegovanobradovic.icet.service.GetUserChats;
import com.njegovanobradovic.icet.service.Update;
import com.njegovanobradovic.icet.util.translate.GoogleAPI;
import com.njegovanobradovic.icet.util.translate.Language;
import com.njegovanobradovic.icet.util.translate.Translate;

public class ControllerImpl implements Controller{
	private Get<User> userList;
	private Update<User> updatedUser;
	private Add<User> addUser;
	private Delete<User> deletedUser;

	private Get<Chat> chatList;
	private Add<Chat> addChat;
	private Update<Chat> updateChat;
	private Delete<Chat> deletedChat;

	private GetUserChats userChats;
	private GetChatUsers chatUsers;
	private GetChatMessages chatMessages;

	private User user;

	public static final String AUTH_TOKEN = "authToken";
	private static Request request;
	private String message;

	// Generated Getters and Setters//
	public Get<User> getUserList() {
		return userList;
	}

	public void setUserList(Get<User> userList) {
		this.userList = userList;
	}

	public Update<User> getUpdatedUser() {
		return updatedUser;
	}

	public void setUpdatedUser(Update<User> updatedUser) {
		this.updatedUser = updatedUser;
	}

	public Add<User> getAddUser() {
		return addUser;
	}

	public void setAddUser(Add<User> addUser) {
		this.addUser = addUser;
	}

	public Delete<User> getDeletedUser() {
		return deletedUser;
	}

	public void setDeletedUser(Delete<User> deletedUser) {
		this.deletedUser = deletedUser;
	}

	public Get<Chat> getChatList() {
		return chatList;
	}

	public void setChatList(Get<Chat> chatList) {
		this.chatList = chatList;
	}

	public Add<Chat> getAddChat() {
		return addChat;
	}

	public void setAddChat(Add<Chat> addChat) {
		this.addChat = addChat;
	}

	public Update<Chat> getUpdateChat() {
		return updateChat;
	}

	public void setUpdateChat(Update<Chat> updateChat) {
		this.updateChat = updateChat;
	}

	public Delete<Chat> getDeletedChat() {
		return deletedChat;
	}

	public void setDeletedChat(Delete<Chat> deletedChat) {
		this.deletedChat = deletedChat;
	}

	public GetUserChats getUserChats() {
		return userChats;
	}

	public void setUserChats(GetUserChats userChats) {
		this.userChats = userChats;
	}

	public GetChatUsers getChatUsers() {
		return chatUsers;
	}

	public void setChatUsers(GetChatUsers chatUsers) {
		this.chatUsers = chatUsers;
	}

	public GetChatMessages getChatMessages() {
		return chatMessages;
	}

	public void setChatMessages(GetChatMessages chatMessages) {
		this.chatMessages = chatMessages;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Request getRequest() {
		return request;
	}

	public void setRequest(Request request) {
		ControllerImpl.request = request;
	}
	
	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	// CommandMethods//
	//User//
	public List<User> getAllUsers() {
		userList.setType(User.class);
		return userList.execute();
	}

	public User updateUser(User user) {
		updatedUser.setObject(user);
		return updatedUser.execute();
	}

	public User deleteUser(String username, String password) {
		User user = checkUser(username, password);
		deletedUser.setObject(user);
		return deletedUser.execute();
	}

	public User addUser(User user) {
		addUser.setObject(user);
		return addUser.execute();
	}
	
	//Chat//
	public List<Chat> getAllChats(){
		chatList.setType(Chat.class);
		return chatList.execute();
	}
	
	public Chat saveChat(Chat chat){
		addChat.setObject(chat);
		return addChat.execute();
	}
	
	public Chat updateChat(Chat chat){
		updateChat.setObject(chat);
		return updateChat.execute();
	}

	//ListMethods//
	public List<Chat> getChatsOfUser(User user){
		userChats.setUser(user);
		return userChats.execute();
	}
	
	public List<User> getUsersFromChat(Chat chat){
		chatUsers.setChat(chat);
		return chatUsers.execute();
	}
	
	public List<Message> getMessagesFromChat(Chat chat) {
		chatMessages.setChat(chat);
		return chatMessages.execute();
	}
	
	//Methods//
	//UserMethods//
	public User getUser(String username) {
		for (User u : getAllUsers()) {
			if (u.getUsername().equals(username))
				return u;
		}
		return null;
	}

	public User checkUser(String username, String password) {
		User user = getUser(username);
		if (user == null) {
			return null;
		}
		if (user.getPassword().equals(password)) {
			return (User) user;
		}
		return null;
	}
	
	public boolean userLogin(String username, String password){
		user = checkUser(username, password);
		if (user!=null) {
			request.getSession(true).setAttribute(AUTH_TOKEN, user);
			user.setStatus(true);
			updateUser(user);
			return true;
		}
		return false;
	}

	public boolean userLogout() {
		Session session = request.getSession(false);
		if (session != null) {
			user.setStatus(false);
			updateUser(user);
			session.setAttribute(AUTH_TOKEN, null);
			session.invalidate();
			return true;
		}
		return false;
	}

	public boolean isLoggedIn() {
		Session session = request.getSession(false);
		if (session != null) {
			return session.getAttribute(AUTH_TOKEN) != null;
		}
		return false;
	}

	public User getLoggedUser() {
		if (isLoggedIn()) {
			user = (User) request.getSession(true).getAttribute(AUTH_TOKEN);
		} else {
			throw new IllegalStateException("The user is not logged ! ");
		}
		return user;
	}
	
	public boolean getLoggedSignal(){
		if (isLoggedIn()) {
			return true;
		}
		return false;
	}
	
	public void removeChatFromChatList(User user, Chat chat){
		getUserChats().setUser(user);
		List<Chat> newList = getUserChats().execute();
		newList.remove(chat);
		user.setChats(newList);
		updateUser(user);
	}
	
	public void signUpUser(User user, String rePassword) {
		if (user.getPassword().equals(rePassword)) {
			if (getUser(user.getUsername()) == null) {
				addUser(user);
				setMessage("You registered successfully! :)");
			} else {
				setMessage("You have to choose different username! :(");
			}
		} else {
			setMessage("You passwords don't match!");
		}
	}

	//ChatMethods//
	public Chat createChat(Chat chat, User u1, User u2) {
		chat.setMessages(new LinkedList<Message>());
		chat.setUsers(new LinkedList<User>());
		chat.setDate(new Date());
		
		Room room = new RoomBean();
		room.setName(u1.getName()+"-"+u2.getName()+" : "+chat.getDate());
		room.setChat(chat);
		room.setDate(chat.getDate());
		chat.setRoom(room);
				
		chat.getUsers().add(u1);
		u1.setChats(getChatsOfUser(u1));
		u1.getChats().add(chat);
		chat.getUsers().add(u2);
		u2.setChats(getChatsOfUser(u2));
		u2.getChats().add(chat);

		saveChat(chat);
		return chat;
	}
	

	public void addWelcomeMessageToChat(String text, Chat chat) {
		Message message = new MessageBean();
		message.setDate(new Date());
		message.setChat(chat);
		message.setContent(text);
		chat.getMessages().add(message);
		updateChat(chat);
	}
	
	public void addMessageToChat(User user,String text, Chat chat) {
		if (user.equals(getChatUsers(chat).get(1))) {
			chat.setReceivedMessage(true);
		}
		Message message = new MessageBean();
		message.setDate(new Date());
		message.setChat(chat);
		message.setContent(user.getName()+": "+text);
		chat.getMessages().add(message);
		updateChat(chat);
	}
	
	public Chat getChat(String name) {
		for (Chat c : getAllChats()) {
			if(c.getRoom().getName().equals(name)){
				return c;
			}
		}
		return null;
	}
	
	public List<User> getChatUsers(Chat chat){
		return getUsersFromChat(chat);
	}
	
	public List<Message> getChatMessages(Chat chat){
		return getMessagesFromChat(chat);
	}
	
	public void removeUserFromChat(User user, Chat chat){
		getUsersFromChat(chat).remove(user);
		updateChat(chat);
	}
	
	//Translator//
	public String translate(String message, Language l1, Language l2){
		try {
			GoogleAPI.setHttpReferrer("http://127.0.0.1:8080");
	        GoogleAPI.setKey("AIzaSyDcXwXEJxw0LeGSNO0i4ntf8WAdFsOfjgw");
	        String translatedText = Translate.DEFAULT.execute(message, l1, l2);
	        return translatedText;
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
}
